package biz

import (
	"github.com/astaxie/beego/cache"
	"t11Lib/t11Errors"
	"t11Lib/t11Log"
	"t11Lib/t11Model"
	"t11Lib/t11Util"
	"time"
	"亚太-iot-服务器/conf"
	"亚太-iot-服务器/models"
)

type devShareIdCache struct {
	c cache.Cache
}

var DevShareIdCache = func() *devShareIdCache {
	ret := &devShareIdCache{}
	bm, err := cache.NewCache("memory", `{"interval":60}`)
	if err != nil {
		panic(err)
	}
	ret.c = bm
	return ret
}()

func (self *devShareIdCache) CacheUserShareId(shareId string, user *models.JwtToken) {
	self.c.Put(shareId, user, time.Minute*5)
}

func (self *devShareIdCache) GetUserByShareId(shareId string) *models.JwtToken {
	val := self.c.Get(shareId)
	if val == nil {
		return nil
	}
	u, ok := val.(*models.JwtToken)
	if ok {
		return u
	}
	return nil
}

func (self *devShareIdCache) DeleteUserByShareId(shareId string) {
	_ = self.c.Delete(shareId)
}

type devShareDao struct{}

var DevShareDao devShareDao

func (self *devShareDao) CreateShareId(user *models.JwtToken) (string, t11Errors.T11Error) {

	userId := []byte(user.ToId() + t11Util.RandString(16))
	_shareId := t11Util.Md5(userId)
	shareId := t11Util.BytesToHexStringWithoutSpace(_shareId)
	DevShareIdCache.CacheUserShareId(shareId, user)
	return shareId, nil
}

func (self *devShareDao) BindShareDeviceCheck(user *models.JwtToken, shareId, devId string) (int, t11Errors.T11Error) {

	errorCode := conf.ErrOk
	conn := t11Model.NewDbConn()

	// 判断绑定的用户是否合法或者绑定时间是否超时
	admin := DevShareIdCache.GetUserByShareId(shareId)
	if admin == nil {
		errorCode = conf.ErrIllegalOrInvalid
		return errorCode, t11Errors.New()
	}

	// 判断是否管理员用户
	if *user == *admin {
		errorCode = conf.ErrIsAdmin
		return errorCode, t11Errors.New()
	}

	// 判断管理员是否有这个设备
	_, err := models.UserDeviceDao.Get(conn, devId, admin)
	if err != nil {
		errorCode = conf.ErrDeviceNotExist
	}

	// 判断该用户是否已绑定
	_, err = models.UserDeviceDao.Get(conn, devId, user)
	if err == nil {
		errorCode = conf.ErrShareDeviceHasBind
	} else {
		errorCode = conf.ErrOk
	}

	return errorCode, err
}

func (self *devShareDao) BindShareDevice(user *models.JwtToken, shareId, devId string) (int, t11Errors.T11Error) {

	errCode, err := self.BindShareDeviceCheck(user, shareId, devId)
	if errCode != conf.ErrOk {
		return errCode, err
	}

	conn := t11Model.NewDbConn()

	// 判断绑定的用户是否合法或者绑定时间是否超时
	admin := DevShareIdCache.GetUserByShareId(shareId)

	err = t11Model.Transacrtion(conn, func() t11Errors.T11Error {

		// 添加绑定关系
		e := models.UserDeviceDao.Create(conn, devId, user.ToId(), admin.ToId(), "share")
		if e != nil {
			return e
		} else {
			return nil
		}
	})

	if err != nil {
		errCode = conf.ErrGeneral
	} else {
		errCode = conf.ErrOk
	}
	// 删除缓存的 shareId
	DevShareIdCache.DeleteUserByShareId(shareId)

	return errCode, err
}

func (self *devShareDao) DeleteByUserId(conn *t11Model.DbConn, userId, devId string) t11Errors.T11Error {

	// 通过遍历该设备下的所有分享用户,找到需要删除的用户
	tokens, err := models.UserDeviceDao.GetTokensByDeviceId(conn, devId)
	if err != nil {
		return err
	}

	for _, token := range tokens {

		id := []byte(token.ToId())
		ret := t11Util.BytesToHexStringWithoutSpace(t11Util.Md5(id))

		// 找到需要删除的用户
		if ret == userId {
			return t11Model.Transacrtion(conn, func() t11Errors.T11Error {

				e := models.UserDeviceDao.Delete(conn, devId, token)
				if e != nil {
					return e
				}

				e = models.UserKvDao.DeleteDeviceKvByUser(conn, devId, token)
				if e != nil {
					return e
				}
				return nil
			})
		}
	}

	return t11Errors.New()
}

func (self *devShareDao) TestCreate() {

	user := models.JwtToken{}

	user.AppType = "weixinMp"
	user.AppId = "wxdac90ea64e64dcfc"
	user.UserId = "oJOuUjvrEpFgQbwCO98w0GpIn_Pg"

	admin := models.JwtToken{}

	admin.AppType = "weixinMp"
	admin.AppId = "wxdac90ea64e64dcfc"
	admin.UserId = "oJOuUjl--WyvGHon5dT24iXeAuFg"

	shareId, _ := DevShareDao.CreateShareId(&admin)
	t11Log.Debuglnf("share id %s", shareId)

	errMsg, _ := DevShareDao.BindShareDevice(&user, shareId, "19074666")
	t11Log.Debuglnf("bind result %s", errMsg)
}
